/*
 * 文件名：RequestFilter.java
 * 版权：MoonBox 
 * 修改人：Peter
 * 修改时间：2018年9月30日
 * 修改内容：新增
 */
package com.renzhebiao.lkang.filter;

import java.io.BufferedReader;
import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.Charsets;
import org.springframework.http.MediaType;
import org.springframework.web.filter.GenericFilterBean;

import com.google.common.base.Strings;
import com.google.common.net.HttpHeaders;
import com.renzhebiao.lkang.request.RequestCache;
import com.renzhebiao.lkang.request.RequestPayload;
import com.renzhebiao.lkang.request.ResettableStreamHttpServletRequest;
import com.renzhebiao.lkang.utils.IPUtils;

import lombok.Cleanup;

/**
 * <p>
 * 请求数据
 * 
 * @author Peter
 * @since 1.0.0
 */
// @Component
public class RequestFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException,
                                                                                          ServletException {
        // ResponseWrapper responseWrapper = new ResponseWrapper(Thread.currentThread().getId(),
        // (HttpServletResponse) response);
        HttpServletRequest request = (HttpServletRequest) req;
        // RequestWrapper requestWrapper = new RequestWrapper(Thread.currentThread().getId(), request);
        String token = request.getHeader("token");// Token
        String ip = IPUtils.getIpAddr(request);// ip
        String uri = request.getRequestURI();// uri
        String contentType = request.getHeader(HttpHeaders.CONTENT_TYPE);// 请求内容类型
        String queryString = request.getQueryString();// 查询字符串
        String originJson = ""; // json
        Long startTime = System.currentTimeMillis();
        String method = request.getMethod().toUpperCase();
        String userAgent = request.getHeader(HttpHeaders.USER_AGENT);
        Byte deviceType = this.getDeviceType(request);
        String url = this.getUrl(uri, queryString);

        // JSON
        if (contentType != null && contentType.toLowerCase().contains(MediaType.APPLICATION_JSON_VALUE)) {
            ResettableStreamHttpServletRequest requestWrapper = new ResettableStreamHttpServletRequest(request);
            requestWrapper.setCharacterEncoding(Charsets.UTF_8.name());
            StringBuffer json = new StringBuffer();
            @Cleanup
            BufferedReader reader = requestWrapper.getReader();
            if (reader != null) {
                String line = null;
                while ((line = reader.readLine()) != null) {
                    json.append(line);
                }
                originJson = json.toString();
                if (originJson.isEmpty()) {
                    originJson = "";
                }
            }
            requestWrapper.resetInputStream(originJson.getBytes(Charsets.UTF_8));
            requestWrapper.overrideContentType(contentType);// MediaType.APPLICATION_JSON_VALUE
            requestWrapper.setParameterMap(request.getParameterMap());
            requestWrapper.setRequestURI(uri);
            req = requestWrapper;
        }
        // String reqJson = originJson.substring(0, 2040);
        RequestCache.set(RequestPayload.builder().deviceType(deviceType).startTime(startTime).url(url).userAgent(userAgent).ip(ip).uri(uri).contentType(contentType).queryString(queryString).reqBody(originJson).startTime(startTime).method(method).token(token).build());
        try {
            chain.doFilter(req, response);
        } finally {
            RequestCache.clean();
        }

    }

    private String getUrl(String uri, String query) {
        String query_ = null;
        if (Strings.isNullOrEmpty(query)) {
            query_ = query;
            return uri;
        }
        return uri + "?" + query_;
    }

    private Byte getDeviceType(HttpServletRequest request) {
        String deviceTypeStr = request.getHeader("DeviceType");
        if (Strings.isNullOrEmpty(deviceTypeStr)) {
            return 0;
        }
        return Byte.valueOf(deviceTypeStr);// device type
    }

}
